package application

import (
	"lnzw/engine/log"
	"reflect"
	"sync"

	"go.uber.org/zap"
)

type Application struct {
	components []IComponent
	close      chan struct{}
}

var globalApplication *Application
var onece = sync.Once{}

type IComponent interface {
	OnInit() error
	OnStart() error
	OnStop() error
}

type BaseComponent struct {
}

func (c *BaseComponent) OnInit() error {
	return nil
}

func (c *BaseComponent) OnStart() error {
	return nil
}

func (c *BaseComponent) OnStop() error {
	return nil
}

// 构建应用
func BuildApplication() *Application {
	onece.Do(func() {
		globalApplication = &Application{
			close:      make(chan struct{}),
			components: make([]IComponent, 0),
		}
	})
	return globalApplication
}

// 注册组件
func (app *Application) Register(component IComponent) {
	app.components = append(app.components, component)
}

// 初始化应用
func (app *Application) Init() {
	defer func() {
		if err := recover(); err != nil {
			log.Logger.Fatal("init application failed", zap.Any("error", err))
		}
	}()
	log.Logger.Info("initing application")
	for _, component := range app.components {
		cType := reflect.TypeOf(component).Elem()
		log.Logger.Info("initing component", zap.Any("component", cType.Name()))
		component.OnInit()
	}
}

// 启动应用
func (app *Application) Start() {
	defer func() {
		if err := recover(); err != nil {
			log.Logger.Fatal("starting application failed", zap.Any("error", err))
		}
	}()
	log.Logger.Info("starting application")
	for _, component := range app.components {
		cType := reflect.TypeOf(component).Elem()
		log.Logger.Info("starting component", zap.Any("component", cType.Name()))
		component.OnStart()
	}
}

// 关闭应用
func (app *Application) Stop() {
	log.Logger.Info("stopping application")
	for _, component := range app.components {
		component.OnStop()
	}
}
